<?php
defined('YII_PATH') or define('YII_PATH',dirname(__FILE__));

class JiBase
{
	public static $classMap=array();

	private static $_aliases=array('system'=>YII_PATH); // alias => path
	private static $_imports=array();					// alias => class name or directory
	private static $_includePaths;						// list of include paths
	
	public static function createApplication($class, $config=null)
	{
		return new $class($config);
	}
	
	public static function createRoute($config=null)
	{
		return self::createApplication('BRoute', $config);
	}
	
	public static function import($alias,$forceInclude=false)
	{
		if(isset(self::$_imports[$alias]))  // previously imported
			return self::$_imports[$alias];

		if(class_exists($alias,false) || interface_exists($alias,false))
			return self::$_imports[$alias]=$alias;

		if(($pos=strrpos($alias,'\\'))!==false) // a class name in PHP 5.3 namespace format
		{
			$namespace=str_replace('\\','.',ltrim(substr($alias,0,$pos),'\\'));
			if(($path=self::getPathOfAlias($namespace))!==false)
			{
				$classFile=$path.DIRECTORY_SEPARATOR.substr($alias,$pos+1).'.php';
				if($forceInclude)
				{
					if(is_file($classFile))
						require($classFile);
					else
						throw new Exception('Alias "{alias}" is invalid. Make sure it points to an existing PHP file.');
					self::$_imports[$alias]=$alias;
				}
				else
					self::$classMap[$alias]=$classFile;
				return $alias;
			}
			else
				throw new Exception('Alias "{alias}" is invalid. Make sure it points to an existing directory.');
		}

		if(($pos=strrpos($alias,'.'))===false)  // a simple class name
		{
			if($forceInclude && self::autoload($alias))
				self::$_imports[$alias]=$alias;
			return $alias;
		}

		$className=(string)substr($alias,$pos+1);
		$isClass=$className!=='*';

		if($isClass && (class_exists($className,false) || interface_exists($className,false)))
			return self::$_imports[$alias]=$className;

		if(($path=self::getPathOfAlias($alias))!==false)
		{
			if($isClass)
			{
				if($forceInclude)
				{
					if(is_file($path.'.php'))
						require($path.'.php');
					else
						throw new Exception('Alias "{alias}" is invalid. Make sure it points to an existing PHP file.');
					self::$_imports[$alias]=$className;
				}
				else
					self::$classMap[$className]=$path.'.php';
				return $className;
			}
			else  // a directory
			{
				if(self::$_includePaths===null)
				{
					self::$_includePaths=array_unique(explode(PATH_SEPARATOR,get_include_path()));
					if(($pos=array_search('.',self::$_includePaths,true))!==false)
						unset(self::$_includePaths[$pos]);
				}

				array_unshift(self::$_includePaths,$path);

				if(set_include_path('.'.PATH_SEPARATOR.implode(PATH_SEPARATOR,self::$_includePaths))===false)
					throw new Exception('Unable to import "{alias}". Please check your server configuration to make sure you are allowed to change PHP include_path.');

				return self::$_imports[$alias]=$path;
			}
		}
		else
			throw new Exception('Alias "{alias}" is invalid. Make sure it points to an existing directory or file.');
	}
	
	public static function getPathOfAlias($alias)
	{
		if(isset(self::$_aliases[$alias]))
			return self::$_aliases[$alias];
		else if(($pos=strpos($alias,'.'))!==false)
		{
			$rootAlias=substr($alias,0,$pos);
			if(isset(self::$_aliases[$rootAlias]))
				return self::$_aliases[$alias]=rtrim(self::$_aliases[$rootAlias].DIRECTORY_SEPARATOR.str_replace('.',DIRECTORY_SEPARATOR,substr($alias,$pos+1)),'*'.DIRECTORY_SEPARATOR);
			else if(self::$_app instanceof BRoute)
			{
				return self::getPathOfAlias($alias);
			}
		}
		return false;
	}
	
	public static function setPathOfAlias($alias,$path)
	{
		if(empty($path))
			unset(self::$_aliases[$alias]);
		else
			self::$_aliases[$alias]=rtrim($path,'\\/');
	}
	
	public static function autoload($className)
	{
		// use include so that the error PHP file may appear
		if(isset(self::$_coreClasses[$className]))
			include(YII_PATH.self::$_coreClasses[$className]);
		else if(isset(self::$classMap[$className]))
			include(self::$classMap[$className]);
		else
		{
			if(strpos($className,'\\')===false)
				include($className.'.php');
			else  // class name with namespace in PHP 5.3
			{
				$namespace=str_replace('\\','.',ltrim($className,'\\'));
				if(($path=self::getPathOfAlias($namespace))!==false)
					include($path.'.php');
				else
					return false;
			}
			return class_exists($className,false) || interface_exists($className,false);
		}
		return true;
	}
	
	public static function registerAutoloader($callback)
	{
		spl_autoload_unregister(array('JiBase','autoload'));
		spl_autoload_register($callback);
		spl_autoload_register(array('JiBase','autoload'));
	}
	
	private static $_coreClasses=array(
		'BRoute'=>'/route/Broute.php',
		'BHttpRequest'=>'/route/BHttpRequest.php',
	);
}

spl_autoload_register(array('JiBase','autoload'));